package com.aiou.security.app.social.openid;

import lombok.Getter;
import lombok.Setter;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.social.connect.UsersConnectionRepository;
import org.springframework.social.security.SocialUserDetails;
import org.springframework.social.security.SocialUserDetailsService;

import java.util.Collections;
import java.util.Set;

/**
 * @author zyb
 */
@Getter
@Setter
public class OpenIdAuthenticationProvider implements AuthenticationProvider {

    private UsersConnectionRepository usersConnectionRepository;
    private SocialUserDetailsService socialUserDetailsService;

    public OpenIdAuthenticationProvider(UsersConnectionRepository usersConnectionRepository, SocialUserDetailsService socialUserDetailsService) {
        this.usersConnectionRepository = usersConnectionRepository;
        this.socialUserDetailsService = socialUserDetailsService;
    }

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        OpenIdAuthenticationToken authenticationToken = (OpenIdAuthenticationToken) authentication;
        Set<String> userIds = usersConnectionRepository.findUserIdsConnectedTo(authenticationToken.getProviderId(), Collections.singleton((String) authenticationToken.getPrincipal()));
        if (userIds.isEmpty() || userIds.size() != 1) {
            throw new InternalAuthenticationServiceException("无法获取用户信息");
        }
        String userId = userIds.iterator().next();
        SocialUserDetails userDetails = socialUserDetailsService.loadUserByUserId(userId);

        OpenIdAuthenticationToken openIdAuthenticationToken = new OpenIdAuthenticationToken(userDetails, userDetails.getAuthorities());
        openIdAuthenticationToken.setDetails(userDetails);
        return openIdAuthenticationToken;
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return OpenIdAuthenticationToken.class.isAssignableFrom(authentication);
    }
}
